import math
import random
from numbers import Real

class Point(object):
    """Point class with public x and y attributes """
    def __init__(self, x=0, y=0, dir=0):
        self.x = float(x)
        self.y = float(y)
        self.dir = float(dir)
 
    def angle(self, p1, p2):
        a = p1.dist(p2)
        b = self.dist(p1)
        c = self.dist(p2)
        cosA = (b*b + c*c - a*a)/(2*b*c)
        return math.acos(cosA) * 180 / math.pi
 
    def tan(self, p):
        return (p.y-self.y)/(p.x-self.x)
 
    def slopeAngle(self, p):
        original = math.atan((p.y-self.y)/(p.x-self.x)) * 180 / math.pi
        if p.x > self.x and p.y > self.y:
            angle = original
        elif p.x > self.x and p.y < self.y:
            angle = original + 360
        elif p.x < self.x and p.y < self.y:
            angle = original + 180
        elif p.x < self.x and p.y > self.y:
            angle = original + 180
        return angle
 
    def atan(self, p):
        return math.atan((p.y-self.y)/(p.x-self.x))
 
    def dist(self, p):
        """return the Euclidian distance between self and p"""
        dx = self.x - p.x
        dy = self.y - p.y
        return math.sqrt(dx*dx + dy*dy)
 
    def reset(self):
        self.x = 0
        self.y = 0

    def __add__(self, p):
        """return a new point found by adding self and p. This method is
        called by e.g. p+q for points p and q"""
        return Point(self.x+p.x, self.y+p.y)
    
    def __sub__(self, p):
        """return a new point found by subtracting self and p. This method is
        called by e.g. p-q for points p and q"""
        return Point(self.x-p.x, self.y-p.y)
    
    def __mul__(self, other):
        if isinstance(other, Real):
            return Point(self.x * other, self.y * other)
        else:
            return NotImplemented
    
#    def __rmul__(self, other):
#        return self.__mul__(other)
 
    def __repr__(self):
        """return a string representation of this point. This method is
        called by the repr() function, and
        also the str() function. It should produce a string that, when
        evaluated, returns a point with the 
        same data."""
        return 'Point(%d,%d)' % (self.x, self.y)

if __name__=="__main__":
    print "hi"
    p = Point(4, 4)
    p1 = Point(7, 8)
    p2 = Point(6, 8)
    print p.angle(p2, p1)
    print p.dist(p1)
    
    
    p2 = Point(0, 0)
#    p3 = Point(3500, 700)
    p3 = Point(500, -500)
    print p2.slopeAngle(p3)

    p4 = Point(-831.20451881829285, 282.1645073515769)
    p5 = Point(-740.07811222122882, 293.53661601889138)
    print p4.slopeAngle(p5)
    
#    p1 = p * random.random()
#    p1 = p * 4.0
#    print p1